#include "mqttclient.h"
#include "../common/config/configmanger.h"
#include "../common/log/log.h"
#include <iostream>
#include <mosquitto.h>
#include <QByteArray>
#include <string.h>


CMqttClient::CMqttClient(QObject *parent)
    : QObject{parent},m_broker(""),
                    m_userName(""),
                    m_PubTopic1(""),

                    m_port(1883),
                    m_password(""),
                    m_dogSn(""),
                    m_dogIp(""),
                    m_ImagesDataTopic(""){
    mosquitto_lib_init();
    this->mosq = mosquitto_new(nullptr, true, this);
    this->setupCallbacks();
    m_keyManager = new KeyBoardManger(this);
    connect(m_keyManager, &KeyBoardManger::SenKeyMsg, this,  &CMqttClient::onSendMsg);
    m_pReciever = CImageReceiver::GetInStance();
}
CMqttClient::~CMqttClient(){
    if (this->mosq) {
        mosquitto_disconnect(this->mosq);
        mosquitto_loop_stop(this->mosq, false);
        mosquitto_destroy(this->mosq);
    }
    mosquitto_lib_cleanup();
}
void CMqttClient::setupCallbacks() {
    mosquitto_connect_callback_set(this->mosq, CMqttClient::connectCallback);
    mosquitto_message_callback_set(this->mosq, CMqttClient::messageCallback);
}
void CMqttClient::Connect(const char* broker, int port, const char* username, const char* password) {
    if (mosquitto_username_pw_set(this->mosq, username, password) != MOSQ_ERR_SUCCESS) {
        LOG_ERROR("Failed to set username and password.");
        return;
    }

    if (mosquitto_connect_async(this->mosq, broker, port, 60) != MOSQ_ERR_SUCCESS) {
        LOG_ERROR("Failed to connect to MQTT broker.");
        return;
    }

    mosquitto_loop_start(this->mosq);
}
void CMqttClient::Subscribe(const char* topic) {
    if (mosquitto_subscribe(this->mosq, nullptr, topic, 0) == MOSQ_ERR_SUCCESS) {
        subscribedTopics.push_back(QString::fromUtf8(topic));
    } else {
        LOG_ERROR("Failed to subscribe to topic.");
    }
}
void CMqttClient::UnSubscribe(const char* topic){
    if (mosquitto_unsubscribe(this->mosq, nullptr, topic) == MOSQ_ERR_SUCCESS) {
        subscribedTopics.removeAll(QString::fromUtf8(topic));
    } else {
        LOG_ERROR("Failed to subscribe to topic.");
    }
}
void CMqttClient::Publish(const char* topic, const char* message) {
    if (mosquitto_publish(this->mosq, nullptr, topic, std::strlen(message), message, 0, false) != MOSQ_ERR_SUCCESS) {
        LOG_ERROR("Failed to publish message.");
    }
}

//发送信令
void CMqttClient::onSendMsg(const QString  &msg){
    LOG_INFO("onSendMsg topic:" << m_PubTopic1.c_str() << "   onSendMsg:  " << msg.toStdString().c_str());
    Publish(m_PubTopic1.c_str(), msg.toStdString().c_str());
}
//初始化获取配置
void CMqttClient::init(){
    //初始化读取配置文件
    std::shared_ptr<CConfigManager> pIntance = CConfigManager::GetInstance();
    if(nullptr != pIntance){
        std::string strPath = "./CFG/config";
        Json::Value tempValue = Json::Value::null;
        if (!pIntance->loadConfig(strPath, tempValue)) {
            LOG_ERROR("Loading Config error!");
            return;
        } else{
            if (tempValue.isMember("MQTT") && tempValue["MQTT"].isObject()){
                if (tempValue["MQTT"].isMember("broker") && tempValue["MQTT"]["broker"].isString()){
                    m_broker = tempValue["MQTT"]["broker"].asCString();
                    LOG_INFO("m_broker: " << m_broker.toStdString());
                }
                if(tempValue["MQTT"].isMember("port") && tempValue["MQTT"]["port"].isInt()){
                    m_port = tempValue["MQTT"]["port"].asInt();
                    LOG_INFO("m_port:{}"<<  m_port);
                }
                if(tempValue["MQTT"].isMember("username") && tempValue["MQTT"]["username"].isString()){
                    m_userName = tempValue["MQTT"]["username"].asCString();
                    LOG_INFO("m_userName: " << m_userName.toStdString());
                }
                if(tempValue["MQTT"].isMember("password") && tempValue["MQTT"]["password"].isString()){
                    m_password = tempValue["MQTT"]["password"].asCString();
                    LOG_INFO("m_password: "<< m_password.toStdString());
                }
                if(tempValue["MQTT"].isMember("subtopic") && tempValue["MQTT"]["subtopic"][0].isString()){
                    m_SubTopic1 = tempValue["MQTT"]["subtopic"][0].asString(); //发布的主题
                    LOG_INFO("m_Topic: " << m_SubTopic1);
                }
                if(tempValue["MQTT"]["subtopic"].size() > 1){
                    if(tempValue["MQTT"].isMember("subtopic") && tempValue["MQTT"]["subtopic"][1].isString()){
                        m_takeOverTopic = tempValue["MQTT"]["subtopic"][1].asString(); //发布的主题
                        LOG_INFO("m_Topic: " << m_takeOverTopic);

                    }
                }
            }
        }
        Connect(m_broker.toStdString().c_str(), m_port, m_userName.toStdString().c_str(), m_password.toStdString().c_str());
        //初始化订阅数据机器人
        if(!m_SubTopic1.empty()){
            Subscribe(m_SubTopic1.c_str());
        }
        if(!m_takeOverTopic.empty()){
            Subscribe(m_takeOverTopic.c_str());
        }
    }
}
void CMqttClient::reconnectAndResubscribe() {

    for (const QString &topic : subscribedTopics) {
        int result = mosquitto_subscribe(this->mosq, nullptr, topic.toStdString().c_str(), 0);
        if(result != MOSQ_ERR_SUCCESS){
            LOG_ERROR("Failed to subscribe to topic "<< topic.toStdString());
        }
    }
}

void CMqttClient::connectCallback(struct mosquitto *mosq, void *obj, int reason_code) {
    if (reason_code == 0) { // Connected successfully
        LOG_INFO("Connected to MQTT Broker.");
        CMqttClient *client = static_cast<CMqttClient*>(obj);
        client->reconnectAndResubscribe();
    } else {
      //  LOG_ERROR("Failed to connect, error code: " + QString::number(reason_code));
    }
}

void CMqttClient::messageCallback(struct mosquitto *mosq, void *obj, const struct mosquitto_message* message) {
    CMqttClient *client =static_cast<CMqttClient*>(obj);
    if (strcmp(message->topic, client->m_ImagesDataTopic.c_str()) == 0) {
        QByteArray data(static_cast<char*>(message->payload), message->payloadlen);
        QMetaObject::invokeMethod(CImageReceiver::GetInStance().get(), "processData", Qt::QueuedConnection, Q_ARG(QByteArray,data));
    }
    if (strcmp(message->topic, "WLRobotics") == 0 ||strcmp(message->topic, "TakeOver") == 0){
        //对获取的数据进行序列化解析
            if(nullptr!= client){
                client->processMsg(message);
            }
        }
}

void CMqttClient::processMsg(const struct mosquitto_message* message){
    if (strcmp(message->topic, "WLRobotics") == 0){
        QString str = (char*) message->payload;
        emit SendBasicDatas(str);
    }
    if(strcmp(message->topic, "TakeOver") == 0){
        //对信息体进行解析
        LOG_INFO( (char*) message->payload);
        QString str = (char*) message->payload;
        emit SendTakeOverInfo(str); //发送接管消息
    }
}

void CMqttClient::SetCmdTopic(const QString &topic){
    m_PubTopic1 = topic.toStdString();
}

void CMqttClient::SendImgRequset(const QString &topic, const QString &message){
    LOG_INFO("message: " << message.toStdString().c_str());
    Publish(topic.toStdString().c_str(), message.toStdString().c_str());
}
void CMqttClient::SendImagesDataTopic(const QString &topic , bool  flag) {
    m_ImagesDataTopic = topic.toStdString();
    if(flag){
        Subscribe(m_ImagesDataTopic.c_str());
    }else{
        UnSubscribe(m_ImagesDataTopic.c_str());
    }
    LOG_INFO("SendImagesDataTopic: "<<m_ImagesDataTopic);
}